I have been working on a program that requires input of currency amounts and decimal percentages into a textbox. As we know, users will sometimes unintentionally add unwanted extra characters in the box, such as a currency symbol ($, £) or a comma, thereby negating the results. I was delighted then, to see the article API Corner - A Numbers-Only Textbox in newsletter 114. It sounded like the answer to the problem. Delight quickly turned to disappointment though, when I discovered that this box would not accept a decimal point, making it useless for my purpose.
I then started browsing through the Liberty BASIC forum, where I saw a thread called "Filtered Numeric Input" by Steve ("chiller") and Alyce, dated January 2004. Steve had written some code that did the job, but I was hoping for something that would not require users to re-enter their input whenever they made a mistake. While working on the problem, I cam up with a function what would accept all the characters that were entered, filter out the unwanted ones, and return just the numerals, the decimal point, and an initial minus sign.
It is far from perfect, (for one thing it has that ugly GOTO in there). A more satisfactory solution would be a textbox that would just not accept the unwanted characters, but it would appear that this capability is just not possible in windows, or else I am sure that Alyce would have had it in our hands by now.
Here is a short program that will demonstrate the function. I hope someone finds this useful.
Bob Bromley
Editor's Note: This program works best with LB4. LB3 will enter an endless loop when it processes the NumberOnly(in$) function.
' FUNCTION NumberOnly$() - Bob Bromley - May 5, 2004
' Function is passed a string, discards any character that is not a number, a decimal point,
' or a minus sign (as long as it preceeds the number) and returns the result.
' NOTE: Numbers > 99,999,999.94 will return in exponential form.
' Numbers > 10,000,000 will round out to the nearest 10¢.
nomainwin
WindowWidth = 300 : WindowHeight = 230
UpperLeftX = int((DisplayWidth - WindowWidth) / 2)
UpperLeftY = int((DisplayHeight - WindowHeight) / 2)
statictext #main.stat.1, "Enter something, (mix characters and numbers)", 35, 15, 290, 20
textbox #main.text.1, 35, 40, 220, 25
statictext #main.stat.2, "The numeric result is", 90, 90, 100, 20
textbox #main.text.2, 55, 115, 180, 25
button #main.butt.1, "Reset", [Reset], UL, 60, 160, 60, 25
button #main.butt.2, "Compute", [Compute], UL, 172, 160, 60, 25
open "Filtered Numeric Input" for window_nf as #main
#main "trapclose [Quit]"
#main.text.1, "¢-¢1,2##-#,$$$-$,$34±®§5-6±§7$(8)9.5#0"
#main.text.1 "!contents? amt$" ' An example, just to get started
amt = NumberOnly(amt$) ' Make the conversion
#main.text.2, trim$(using("############.##", amt)) ' Put the result in the lower textbox
WAIT
[Compute]
#main.text.1 "!contents? amt$" ' Get the user's input
' We must allow decimal points, but more than 1 will give us an incorrect return.
' So the first thing to do is count them, and stop here if there is more than 1.
' Use this for severe error-checking.
t = 0
for i = 1 to len(amt$)
t$ = mid$(amt$, i, 1) : if t$ = "." then t = t + 1
if t > 1 then notice "Only 1 decimal point is allowed in the number! " : wait
next
amt = NumberOnly(amt$) ' Make the conversion
#main.text.2, trim$(using("############.##", amt)) ' Put the result in the lower textbox
WAIT
[Reset] ' Blank both the textboxes
#main.text.1, ""
#main.text.2, ""
#main.text.1 "!setfocus" ' Put the cursor in the upper textbox
WAIT
[Quit]
close #main
END
FUNCTION NumberOnly(in$) ' Here is the meat of it!
[Start]
for i = 1 to len(in$)
t$ = mid$(in$, i, 1)
select case
' Do nothing if t$ is a numeral or a decimal point
case asc(t$) = 46 OR (asc(t$) > 47) AND (asc(t$) < 58)
' A minus sign is ok, as long as it preceeds the numbers
case asc(t$) = 45 AND i = 1
' Discard any other character
case else
in$ = left$(in$, i - 1) + right$(in$, len(in$) - i)
goto [Start]
end select
next
NumberOnly = val(in$)
END FUNCTION